﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Luminal
{
    public sealed partial class CommandQueue : LuminalObject
    {
        #region Kernel Execution
        public Event EnqueueNDRangeKernel(Kernel kernel, int[] globalWorkSizes, int[] localWorkSizes, params Event[] waitList)
        {
            if (kernel == null)
                throw new ArgumentNullException("kernel");
            if (kernel.Disposed)
                throw new ObjectDisposedException("kernel");
            if (localWorkSizes != null && localWorkSizes.Length != globalWorkSizes.Length)
                throw new ArgumentException("The dimensions of the local work sizes must equal that of the global work sizes.", "localWorkSizes");
            if (waitList != null && waitList.Any(n => n.Disposed))
                throw new ObjectDisposedException("waitList");
            if (waitList != null && waitList.Length == 0)
                waitList = null;

            SizeT[] global_work_size = new SizeT[globalWorkSizes.Length];
            for (int i = 0; i < globalWorkSizes.Length; i++)
                global_work_size[i] = globalWorkSizes[i];

            SizeT[] local_work_size = localWorkSizes == null ? null : new SizeT[localWorkSizes.Length];
            if (localWorkSizes != null)
            {
                for (int i = 0; i < localWorkSizes.Length; i++)
                    local_work_size[i] = localWorkSizes[i];
            }

            IntPtr[] waitListPtrs = (waitList == null || waitList.Length == 0) ? null : Util.ExtractPointers<Event>(waitList);

            IntPtr evt = default(IntPtr);
            Util.ThrowError("Failed to queue command.",
                clEnqueueNDRangeKernel(InternalPointer, kernel.InternalPointer, (uint)globalWorkSizes.Length, null, global_work_size, local_work_size, waitList == null ? 0 : (uint)waitList.Length, waitListPtrs, out evt));

            return Event.FromHandle(evt);
        }
        #endregion
    }
}
